#ifndef LOG_H
#define LOG_H

#include <string>
#include <sstream>
#include <memory>
#include <cstdarg>
#include <fstream>
#include <iostream>

#include "../utils/utils.h"
#include "singleTo.h"


#define LOG_LEVEL(loggle, level) \
    hps::LogEventWarp(hps::LogEvent::ptr(new hps::LogEvent(loggle, __FILE__, hps::GetCurrentMS(), __LINE__, level)), level).getSS()

#define LOG_DEBUG(logger)  LOG_LEVEL(logger, hps::LogLevel::DEBUG)
#define LOG_INFO(logger)   LOG_LEVEL(logger, hps::LogLevel::INFO)
#define LOG_WARN(logger)   LOG_LEVEL(logger, hps::LogLevel::WARNNING)
#define LOG_ERROR(logger)  LOG_LEVEL(logger, hps::LogLevel::ERROR)
#define LOG_FATAL(logger)  LOG_LEVEL(logger, hps::LogLevel::FATAL)

#define LOG_ROOT() hps::LoggerMgr::GetInstance() -> getRoot()


namespace hps {

class Logger;

// 日志等级
class LogLevel {
public:
    enum Level {
        UNKNOW = 0,
        DEBUG = 1,
        INFO = 2,
        WARNNING = 3,
        ERROR = 4,
        FATAL = 5
    };
    static const char *ToString(LogLevel::Level level);
    static LogLevel::Level FromString(std::string &str);
};

// 日志事件
class LogEvent {
public:
    typedef std::shared_ptr<LogEvent> ptr;
public:
    LogEvent(std::shared_ptr<Logger> logger, const char *file, uint64_t time, uint32_t line, LogLevel::Level level);
    uint64_t getTime() const { return m_time; }
    uint32_t getLine() const { return m_line; }
    std::shared_ptr<Logger> getLogger() const { return m_logger; }
    std::stringstream &getSS() { return m_ss; }
    const char *getFileName() const { return m_file; }

public:
    void format(const char *fmt, ...);
    void format(const char *fmt, va_list vaList);
    std::string format();
private:
    const char *m_file = nullptr; // 文件名
    uint64_t m_time;              // 时间
    uint32_t m_line;              // 行号
    std::stringstream m_ss;       // 内容
    LogLevel::Level m_level;
    std::shared_ptr<Logger> m_logger;
};

class LogEventWarp {
public:
    std::shared_ptr<LogEventWarp> ptr;
public:
    LogEventWarp(LogEvent::ptr event, LogLevel::Level level);
    ~LogEventWarp();
    // 从LogEventWrap返回一个stringstream用于接收日志内容
    std::stringstream &getSS();
private:
    LogEvent::ptr m_event;
    LogLevel::Level m_level;
};

// 日志生成
class Logger {
public:
    typedef std::shared_ptr<Logger> ptr;
public:
    // 不同等级的日志
    void unknow(LogEvent::ptr event);
    void debug(LogEvent::ptr event);
    void info(LogEvent::ptr event);
    void warnning(LogEvent::ptr event);
    void fatal(LogEvent::ptr event);
    void error(LogEvent::ptr event);
public:
    Logger();
    // 将日志写进文件中
    void log(LogLevel::Level level, LogEvent::ptr event);

public:
    // 重新打开文件
    bool reopen();
    // 设置的存放日志的文件
    void setFile(std::string file);
    // 获取日志文件名
    std::string getFileName() const { return m_fileName; }
private:
    std::string m_fileName;
    std::ofstream m_fileStream;
};

class LoggerManager {
public:
    LoggerManager();
    Logger::ptr getRoot() const { return m_root; }
private:
    Logger::ptr m_root;
};

typedef hps::Singleton<LoggerManager> LoggerMgr;

}

#endif